package com.laiketui.order.service.impl;

import cn.afterturn.easypoi.entity.ImageEntity;
import cn.afterturn.easypoi.excel.ExcelExportUtil;
import cn.afterturn.easypoi.excel.entity.TemplateExportParams;
import com.alibaba.fastjson.JSON;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.laiketui.common.api.PublicMemberService;
import com.laiketui.common.mapper.*;
import com.laiketui.core.exception.LaiKeAPIException;
import com.laiketui.core.utils.help.SpringHelper;
import com.laiketui.core.utils.tool.DataUtils;
import com.laiketui.core.utils.tool.DateUtil;
import com.laiketui.domain.config.ConfiGureModel;
import com.laiketui.domain.lktconst.ErrorCode;
import com.laiketui.domain.mch.CartModel;
import com.laiketui.domain.mch.MchModel;
import com.laiketui.domain.product.ProductListModel;
import com.laiketui.domain.user.User;
import com.laiketui.domain.user.UserAddress;
import com.laiketui.order.api.dto.*;
import com.laiketui.order.api.enums.*;
import com.laiketui.order.api.params.AgainConfirmOrderParams;
import com.laiketui.order.api.params.AgainPlaceOrderParams;
import com.laiketui.order.api.params.UserPlaceOrderParams;
import com.laiketui.order.api.params.store.*;
import com.laiketui.order.common.RedissonLock;
import com.laiketui.order.domain.Order;
import com.laiketui.order.domain.OrderDetail;
import com.laiketui.order.domain.OrderParent;
import com.laiketui.order.domain.OrderParentMessage;
import com.laiketui.order.entity.OrderCombiner;
import com.laiketui.order.entity.OrderDetailEntity;
import com.laiketui.order.mapstruct.OrderDetailMapstructMapper;
import com.laiketui.order.mapstruct.PlaceOrderParamsMapstructMapper;
import com.laiketui.order.runner.OrderCancelRunner;
import com.laiketui.order.service.*;
import com.laiketui.order.utils.AmountConverter;
import com.laiketui.order.utils.PriceUtil;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.apache.poi.ss.usermodel.*;
import org.apache.poi.ss.util.CellRangeAddress;
import org.jetbrains.annotations.NotNull;
import org.redisson.client.protocol.decoder.ObjectMapDecoder;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.core.io.ClassPathResource;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.CollectionUtils;
import tk.mybatis.mapper.entity.Example;

import javax.imageio.ImageIO;
import java.awt.image.BufferedImage;
import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.math.BigDecimal;
import java.net.URL;
import java.util.*;
import java.util.stream.Collectors;

@Slf4j
@Service
public class OrderProcessServiceImpl implements OrderProcessService {

    private static final String ORDER_PARENT_PREFIX = "order_parent_";
    private static final String SPLIT_STR = ",";

    @Autowired
    private RedissonLock redissonLock;
    @Autowired
    private OrderParentServiceImpl orderParentServiceImpl;
    @Autowired
    private OrderService orderService;
    @Autowired
    private OrderDetailService orderDetailService;
    @Autowired
    private OrderParentMessageService orderParentMessageService;
    @Autowired
    private PublicMemberService publicMemberService;
    @Autowired
    private ProductListModelMapper productListModelMapper;
    @Autowired
    private UserMapper userMapper;
    @Autowired
    private ConfiGureModelMapper configureModelMapper;
    @Autowired
    private CartModelMapper cartModelMapper;
    @Autowired
    private OrderMessageService orderMessageService;

    @Override
    public boolean cancelOrder(String orderParentNo, String cancelReason) {
        OrderParent orderParent = orderParentServiceImpl.getOrderParent(orderParentNo);
        if (!OrderParentStatusEnum.WAIT_PAY.getCode().equals(orderParent.getStatus())) {
            return false;
        }
        redissonLock.lock(getOrderParentLockKey(orderParentNo));
        try {
            OrderProcessServiceImpl processService = SpringHelper.getBeanInfo(OrderProcessServiceImpl.class);
            processService.cancelOrderTransactional(orderParentNo, cancelReason);
            return true;
        } catch (Exception e) {
            log.error("取消订单失败:{}", e.getMessage());
            return false;
        } finally {
            redissonLock.unlock(getOrderParentLockKey(orderParentNo));
        }

    }

    @Transactional
    public void cancelOrderTransactional(String orderParentNo, String cancelReason) {
        OrderParent orderParent = orderParentServiceImpl.getOrderParent(orderParentNo);
        if (!OrderParentStatusEnum.WAIT_PAY.getCode().equals(orderParent.getStatus())) {
            return;
        }
        boolean b = orderParentServiceImpl.updateStatusCancel(orderParentNo, cancelReason);
        if (!b) {
            return;
        }
        orderService.updateStatusCancel(orderParentNo);
        orderDetailService.updateStatusCancel(orderParentNo);
        orderParentMessageService.addOrderParentMessage(orderParent.getUserId(), orderParent.getStoreId(), OrderParentMessageType.ORDER_PAY_TIMEOUT.getCode(), orderParentNo, OrderParentStatusEnum.CANCEL.getCode(), OrderParentMessageType.ORDER_PAY_TIMEOUT.getName());
        OrderCancelRunner.removeOrderCancel(orderParentNo);
    }

    public static @NotNull String getOrderParentLockKey(String orderParentNo) {
        return ORDER_PARENT_PREFIX + orderParentNo;
    }


    @Override
    public String buyAgainToCart(AgainConfirmOrderParams confirmOrderParams, User user) {
        if (StringUtils.isBlank(confirmOrderParams.getOrderParentNo())) {
            throw new LaiKeAPIException(ErrorCode.BizErrorCode.PARAMATER_ERROR, "母单号不能为空");
        }
        List<OrderDetail> details = orderDetailService.findByOrderParentNo(confirmOrderParams.getOrderParentNo());
        if (CollectionUtils.isEmpty(details)) {
            throw new LaiKeAPIException(ErrorCode.BizErrorCode.ERROR_CODE_HQDDQRXXSB, "未查询母单信息", "againConfirmOrder");
        }
        //获取未下架的商品和未下架的sku列表
        List<ProductListModel> productListModelsByCarts = getProductListModelsByOrderDetailIds(details);
        if (CollectionUtils.isEmpty(productListModelsByCarts)) {
            throw new LaiKeAPIException(ErrorCode.BizErrorCode.ERROR_CODE_HQDDQRXXSB, "未查询到商品信息", "confirmOrder");
        }
        List<OrderDetail> orderDetails = new LinkedList<>(details);
        List<Integer> offlineProductIds = new ArrayList<>(productListModelsByCarts.size());
        for (ProductListModel productListModel : productListModelsByCarts) {
            if ("3".equals(productListModel.getStatus())) {
                offlineProductIds.add(productListModel.getId());
            }
        }
        Iterator<OrderDetail> iterator = orderDetails.iterator();
        if (!CollectionUtils.isEmpty(offlineProductIds)) {
            while (iterator.hasNext()) {
                OrderDetail orderDetail = iterator.next();
                if (offlineProductIds.contains(orderDetail.getProductId())) {
                    iterator.remove();
                }
            }
        }

        if (CollectionUtils.isEmpty(orderDetails)) {
            throw new LaiKeAPIException(ErrorCode.BizErrorCode.ERROR_CODE_HQDDQRXXSB, "所有商品都已下架", "againConfirmOrder");
        }

        List<ConfiGureModel> skuList = getSkuListByOrderDetails(orderDetails);
        if (CollectionUtils.isEmpty(skuList)) {
            throw new LaiKeAPIException(ErrorCode.BizErrorCode.ERROR_CODE_HQDDQRXXSB, "未查询到商品sku信息", "againConfirmOrder");
        }

        //删除已下架的sku
        List<Integer> offLineSkuIds = new ArrayList<>(skuList.size());
        for (ConfiGureModel confiGureModel : skuList) {
            if ("3".equals(confiGureModel.getStatus())) {
                offLineSkuIds.add(confiGureModel.getId());
            }
        }
        iterator = orderDetails.iterator();
        if (!CollectionUtils.isEmpty(offLineSkuIds)) {
            while (iterator.hasNext()) {
                OrderDetail orderDetail = iterator.next();
                if (offLineSkuIds.contains(orderDetail.getSkuId())) {
                    iterator.remove();
                }
            }
        }
        if (CollectionUtils.isEmpty(orderDetails)) {
            throw new LaiKeAPIException(ErrorCode.BizErrorCode.ERROR_CODE_HQDDQRXXSB, "未查询到商品信息", "confirmOrder");
        }
        List<CartModel> cartModelsByOrderDetails = getCartModelsByOrderDetails(orderDetails);
        cartModelsByOrderDetails.forEach(cartModel -> {
            cartModel.setCreate_time(new Date());
            cartModel.setToken(confirmOrderParams.getAccessId());
        });
        cartModelMapper.insertList(cartModelsByOrderDetails);
        List<String> cartIds = cartModelsByOrderDetails.stream().map(cartModel -> String.valueOf(cartModel.getId())).collect(Collectors.toList());
        return String.join(SPLIT_STR, cartIds);
    }

    @Override
    public boolean updateEstimatedDeliveryTime(String orderParentNo, Date estimatedDeliveryTime) {
        OrderParent orderParent = orderParentServiceImpl.getOrderParent(orderParentNo);
        if (!OrderParentStatusEnum.WAIT_SEND.getCode().equals(orderParent.getStatus())) {
            return true;
        }
        redissonLock.lock(getOrderParentLockKey(orderParentNo));
        try {
            OrderProcessServiceImpl processService = SpringHelper.getBeanInfo(OrderProcessServiceImpl.class);
            processService.updateEstimatedDeliveryTimeTransactional(orderParentNo, estimatedDeliveryTime);
            return true;
        } catch (Exception e) {
            log.error("更新预计发货时间订单失败:{}", e.getMessage());
            return false;
        } finally {
            redissonLock.unlock(getOrderParentLockKey(orderParentNo));
        }
    }

    @Override
    public boolean finishOrderParent(String orderParentNo, String orderNo, String userId) {
        OrderParent orderParent = orderParentServiceImpl.getOrderParent(orderParentNo);
        if (!OrderParentStatusEnum.WAIT_SEND.getCode().equals(orderParent.getStatus())) {
            log.info("母单:{}  状态:{}", orderParentNo, orderParent.getStatus());
            return false;
        }
        redissonLock.lock(getOrderParentLockKey(orderParentNo));
        try {
            LambdaQueryWrapper<Order> orderQueryWrapper = new LambdaQueryWrapper<Order>();
            orderQueryWrapper.eq(Order::getOrderParentNo, orderParentNo)
                    .ne(Order::getOrderNo, orderNo)
                    .eq(Order::getDeleted, DelFlagEnum.NORMAL.getCode())
                    .eq(Order::getStatus, OrderStatusEnum.WAIT_SEND.getCode());
            List<Order> list = orderService.list(orderQueryWrapper);
            log.info("查询排除{}子单后剩余未发货子单数量:{}", orderNo, list.size());
            if (CollectionUtils.isEmpty(list)) {
                OrderParent updateOrderParent = new OrderParent();
                updateOrderParent.setUpdateBy(userId);
                Date now = new Date();
                updateOrderParent.setUpdateTime(now);
                Calendar calendar = Calendar.getInstance();
                calendar.setTime(now);
                calendar.add(Calendar.DAY_OF_MONTH, 2);
                //真实发货时间晚两天
                Date realDeliveryTime = calendar.getTime();
                updateOrderParent.setRealDeliveryTime(realDeliveryTime);
                updateOrderParent.setStatus(OrderParentStatusEnum.WAIT_RECEIVE.getCode());
                boolean b = orderParentServiceImpl.updateByOrderParentNo(orderParentNo, updateOrderParent);
                log.info("更新母单状态为已发货:{}", orderParentNo);
                orderParentMessageService.addOrderParentMessage(userId, orderParent.getStoreId(), OrderParentMessageType.ORDER_RECEIVE.getCode(), orderParentNo, OrderParentStatusEnum.WAIT_RECEIVE.getCode(), "订单已发货");
                log.info("添加发货成功消息:{}", orderParentNo);
                return b;
            }
        } finally {
            redissonLock.unlock(getOrderParentLockKey(orderParentNo));
        }
        return false;
    }


    @Override
    public Workbook export(String orderParentNo) {

        // 模板路径
        String templatePath = "templates/user_order_template.xlsx";


        TemplateExportParams params = new TemplateExportParams(templatePath);

        // 创建导出数据
        Map<String, Object> data = new HashMap<>();
        OrderParent orderParent = orderParentServiceImpl.getOrderParent(orderParentNo);
        data.put("orderParentNo", orderParent.getOrderParentNo());
        data.put("name", orderParent.getName());
        data.put("mobile", orderParent.getMobile());
        data.put("remark", orderParent.getRemark());
        data.put("address", orderParent.getProvice() + orderParent.getCity() + orderParent.getArea() + orderParent.getAddress());


        List<Order> orders = orderService.findByOrderParentNo(orderParentNo);
        StringBuilder mchRemarkSB = new StringBuilder();
        for (Order order : orders) {
            if (StringUtils.isNotBlank(order.getMchRemark())) {
                mchRemarkSB.append(order.getMchRemark());
            }
            mchRemarkSB.append(",");
        }
        //指定发货时间
        data.put("specifyDeliveryTime", "");
        if (!CollectionUtils.isEmpty(orders) && Objects.nonNull(orders.get(0)) && Objects.nonNull(orders.get(0).getSpecifyDeliveryTime())) {
            //指定发货时间
            String value = DateUtil.dateFormate(orders.get(0).getSpecifyDeliveryTime(), "yyyy/MM/dd");
            data.put("specifyDeliveryTime", value);
        }

        String mchRemark = mchRemarkSB.toString();
        data.put("mchRemark", mchRemark.substring(0, mchRemark.length() - 1));

        List<OrderDetail> orderDetails = orderDetailService.findByOrderParentNo(orderParentNo);
        List<OrderDetailEntity> dtOs = OrderDetailMapstructMapper.INSTANCE.toEntitys(orderDetails);
        int nums = 0;
        for (int i = 0; i < dtOs.size(); i++) {
            OrderDetailEntity orderDetailDTO = dtOs.get(i);
            orderDetailDTO.setSort(i + 1);
            setImageEntity(orderDetailDTO);
            nums += orderDetailDTO.getNum();
        }
        data.put("orderDetails", dtOs);
        data.put("num", nums);
        BigDecimal value = PriceUtil.longToBigDecimalPrice(orderParent.getTotalPrice());
        data.put("totalPrice", value);
        data.put("totalPriceM", AmountConverter.toChineseUpperCase(value));

        Workbook workbook = ExcelExportUtil.exportExcel(params, data);
        CellStyle style = createStyle(workbook);
        style.setAlignment(HorizontalAlignment.CENTER);

        CellStyle styleRight = createStyle(workbook);
        styleRight.setAlignment(HorizontalAlignment.RIGHT);

        CellStyle styleLeft = createStyle(workbook);
        styleRight.setAlignment(HorizontalAlignment.LEFT);

        Sheet sheet = workbook.getSheetAt(0);
        int lastRowNum = 6 + dtOs.size();
        CellStyle borderStyle = createBorderStyle(workbook);
        lastRowNum++;
        sheet.addMergedRegion(new CellRangeAddress(lastRowNum, lastRowNum, 0, 5));
        Row row = sheet.createRow(lastRowNum);
//        row.setRowStyle(style);
        createCell(row,borderStyle);
        Cell cell1 = row.createCell(0);
        cell1.setCellValue("合计:");
        cell1.setCellStyle(styleRight);


        Cell cell2 = row.createCell(6);
        cell2.setCellValue(nums);
        cell2.setCellStyle(style);
        cell2.getCellStyle().setAlignment(HorizontalAlignment.CENTER);

        row.createCell(7).setCellStyle(style);
        row.createCell(9).setCellStyle(style);
        row.createCell(10).setCellStyle(style);

        Cell cell3 = row.createCell(8);
        cell3.setCellValue(value.toString());
        cell3.setCellStyle(style);
        cell3.getCellStyle().setAlignment(HorizontalAlignment.CENTER);

        lastRowNum++;
        sheet.addMergedRegion(new CellRangeAddress(lastRowNum, lastRowNum, 0, 5));
        sheet.addMergedRegion(new CellRangeAddress(lastRowNum, lastRowNum, 6, 10));
        row = sheet.createRow(lastRowNum);
//        row.setRowStyle(style);
        createCell(row,borderStyle);
        Cell cell = row.createCell(0);
        cell.setCellValue("合计大写总金额:");
        cell.setCellStyle(styleRight);
        cell.getCellStyle().setAlignment(HorizontalAlignment.RIGHT);


        Cell cellM = row.createCell(6);
        cellM.setCellValue(AmountConverter.toChineseUpperCase(value));
        cellM.setCellStyle(styleLeft);

        row.createCell(10).setCellStyle(style);
        row.createCell(8).setCellStyle(style);


        return workbook;
    }

    private static void createCell(Row row, CellStyle borderStyle) {
        for (int j=0;j<11;j++){
            row.createCell(j).setCellStyle(borderStyle);
        }
    }
    private static @NotNull CellStyle createBorderStyle(Workbook workbook) {
        CellStyle style = workbook.createCellStyle();
        // 设置边框
        style.setBorderTop(BorderStyle.THIN); // 顶部边框
        style.setBorderBottom(BorderStyle.THIN); // 底部边框
        style.setBorderLeft(BorderStyle.THIN); // 左边边框
        style.setBorderRight(BorderStyle.THIN); // 右边边框
        return style;
    }

    private static void setImageEntity(OrderDetailEntity orderDetailDTO) {
        URL imageUrl = null;
        ByteArrayOutputStream byteArrayOut = new ByteArrayOutputStream();
        try {
            imageUrl = new URL(orderDetailDTO.getImg());
            BufferedImage bufferImg = ImageIO.read(imageUrl);
            ImageIO.write(bufferImg, "jpg", byteArrayOut);
            ImageEntity imageEntity = new ImageEntity(byteArrayOut.toByteArray(), 100, 50);
            orderDetailDTO.setImageEntity(imageEntity);
        } catch (IOException e) {
            e.printStackTrace();
        } finally {
            try {
                byteArrayOut.close();
            } catch (IOException e) {

            }
        }
    }

    @Transactional
    @Override
    public String editExpectedDeliveryTime(StoreEditExpectedDeliveryTimeParams params) {

        OrderParent orderParent = new OrderParent();
        orderParent.setUpdateBy(params.getAdminId().toString());
        Date now = new Date();
        orderParent.setUpdateTime(now);
        orderParent.setExpectedDeliveryTime(params.getExpectedDeliveryTime());
        boolean b = orderParentServiceImpl.updateByOrderParentNo(params.getOrderParentNo(), orderParent);
        log.info("更新母单期望发货时间成功:{} {}", params.getOrderParentNo(), params.getExpectedDeliveryTime());

        LambdaQueryWrapper<Order> wrapper = new LambdaQueryWrapper<>();
        wrapper.eq(Order::getOrderParentNo, params.getOrderParentNo());
        Order order = new Order();
        order.setExpectedDeliveryTime(params.getExpectedDeliveryTime());
        order.setUpdateBy(params.getAdminId().toString());
        order.setUpdateTime(now);
        orderService.update(order,wrapper);
        log.info("更新母单下所有子单期望发货时间成功:{} {}", params.getOrderParentNo(), params.getExpectedDeliveryTime());

        OrderParent queryOrderParent = orderParentServiceImpl.getOrderParent(params.getOrderParentNo());
        String messageContent = "修改期望发货时间为:" + DateUtil.dateFormate(params.getExpectedDeliveryTime(), "yyyy-MM-dd");
        orderParentMessageService.addOrderParentMessage(params.getAdminId().toString(), params.getStoreId(), OrderParentMessageType.EDIT_EXPECTED_DELIVERY_TIME.getCode(), params.getOrderParentNo(), queryOrderParent.getStatus(), messageContent);
        return params.getOrderParentNo();
    }

    @Transactional
    @Override
    public String editDelivery(StoreEditDeliveryParams params) {
        Date now = new Date();
        OrderParent orderParent = new OrderParent();
        orderParent.setUpdateBy(params.getAdminId().toString());
        orderParent.setUpdateTime(now);
        orderParent.setProvice(params.getProvice());
        orderParent.setCity(params.getCity());
        orderParent.setArea(params.getArea());
        orderParent.setName(params.getName());
        orderParent.setMobile(params.getMobile());
        orderParent.setAddress(params.getAddress());
        orderParentServiceImpl.updateByOrderParentNo(params.getOrderParentNo(), orderParent);
        log.info("更新母单收货地址成功");

        Order order = new Order();
        order.setUpdateBy(params.getAdminId().toString());
        order.setUpdateTime(now);
        order.setProvice(params.getProvice());
        order.setCity(params.getCity());
        order.setArea(params.getArea());
        order.setName(params.getName());
        order.setMobile(params.getMobile());
        order.setAddress(params.getAddress());
        orderService.updateByOrderParentNo(params.getOrderParentNo(), order);
        log.info("更新子单收货地址成功");


        OrderParent queryOrderParent = orderParentServiceImpl.getOrderParent(params.getOrderParentNo());
        String messageContent = "修改发货地址:" + params.getProvice() + params.getCity() + params.getArea() + params.getAddress();
        orderParentMessageService.addOrderParentMessage(params.getAdminId().toString(), params.getStoreId(), OrderParentMessageType.EDIT_DELIVERY.getCode(), params.getOrderParentNo(), queryOrderParent.getStatus(), messageContent);
        return params.getOrderParentNo();
    }

    @Transactional
    @Override
    public String editMchRemark(StoreEditMchRemarkParams params) {
        Order order = new Order();
        order.setUpdateTime(new Date());
        order.setUpdateBy(params.getAdminId().toString());
        order.setMchRemark(params.getMchRemark());
        orderService.updateByOrderNo(order, params.getOrderNo());
        log.info("更新子单工厂备注:{}", params.getOrderNo());

        Order queryOrder = orderService.findByOrderNo(params.getOrderNo());
        orderMessageService.addOrderMessage(params.getOrderNo(), params.getAdminId().toString(), "修改工厂备注", queryOrder.getStatus(), queryOrder.getOrderParentNo(), "", params.getMchRemark(), OrderMessageTypeEnum.EDIT_MCH_REMARK, params.getAdminId().toString());
        return params.getOrderNo();
    }

    @Transactional
    @Override
    public String editRemark(StoreEditRemarkParams params) {
        OrderParent orderParent = new OrderParent();
        orderParent.setUpdateTime(new Date());
        orderParent.setUpdateBy(params.getAdminId().toString());
        orderParent.setRemark(params.getRemark());
        orderParentServiceImpl.updateByOrderParentNo(params.getOrderParentNo(), orderParent);
        log.info("更新母单备注:{}", params.getOrderParentNo());
        OrderParent queryOrderParent = orderParentServiceImpl.getOrderParent(params.getOrderParentNo());
        orderParentMessageService.addOrderParentMessage(params.getAdminId().toString(), params.getStoreId(), OrderParentMessageType.EDIT_REMARK.getCode(),
                params.getOrderParentNo(), queryOrderParent.getStatus(), "修改订单备注:" + params.getRemark());
        return "";
    }

    @Transactional
    @Override
    public String editDeliverNo(StoreEditDeliverNoParams params) {
        Order order = new Order();
        order.setUpdateTime(new Date());
        order.setUpdateBy(params.getAdminId().toString());
        order.setDeliverNo(params.getDeliverNo());
        orderService.updateByOrderNo(order, params.getOrderNo());
        log.info("更新子单物流单号:{}", params.getOrderNo());

        Order queryOrder = orderService.findByOrderNo(params.getOrderNo());
        orderMessageService.addOrderMessage(params.getOrderNo(), params.getAdminId().toString(), "修改物流单号:" + params.getDeliverNo(), queryOrder.getStatus(), queryOrder.getOrderParentNo(), "", "", OrderMessageTypeEnum.EDIT_DELIVER_NO, params.getAdminId().toString());
        log.info("根据物流单号增加消息完成");
        if (params.isSync()) {
            orderService.updateByOrderParentNo(queryOrder.getOrderParentNo(), order);
        }
        return params.getOrderNo();
    }

    @Override
    public String editQualityInspection(StoreEditQualityInspectionParams params) {
        OrderDetail orderDetail = new OrderDetail();
        orderDetail.setQualityInspection(params.getQualityInspection());
        orderDetail.setUpdateTime(new Date());
        orderDetail.setUpdateBy(params.getAdminId().toString());
        LambdaQueryWrapper<OrderDetail> wrapper = new LambdaQueryWrapper<>();
        wrapper.eq(OrderDetail::getDetailNo, params.getOrderDetailNo());
        orderDetailService.update(orderDetail, wrapper);
        return params.getOrderDetailNo();
    }

    @Override
    public boolean finish(StoreFinishParams params) {
        OrderParent orderParent = new OrderParent();
        Date now = new Date();
        orderParent.setUpdateTime(now);
        orderParent.setUpdateBy(params.getAdminId().toString());
        Date finishTime = now;
        if(Objects.nonNull(params.getFinishTime())){
            finishTime=params.getFinishTime();
        }
        orderParent.setFinishTime(finishTime);
        orderParent.setStatus(OrderParentStatusEnum.FINISH.getCode());
        boolean b = orderParentServiceImpl.updateByOrderParentNo(params.getOrderParentNo(), orderParent);
        log.info("更新母单完成时间,完成状态:{}", params.getOrderParentNo());

        OrderParent queryOrderParent = orderParentServiceImpl.getOrderParent(params.getOrderParentNo());
        orderParentMessageService.addOrderParentMessageAndPhotoAndRemark(params.getAdminId().toString(), params.getStoreId(), OrderParentMessageType.ORDER_PARENT_FINISH.getCode(),
                params.getOrderParentNo(), queryOrderParent.getStatus(), "收货完成",params.getPhoto(),params.getRemark());

        return b;
    }

    @Override
    public boolean addOrderParentMessage(StoreAddParentMessageParams params) {
        OrderParent orderParent = orderParentServiceImpl.getOrderParent(params.getOrderParentNo());
        String messageContent = "跟踪订单";
        if (StringUtils.isNotBlank(params.getRemark())) {
            messageContent += ":";
            messageContent += params.getRemark();
        }
        OrderParentMessage orderParentMessage = orderParentMessageService.addOrderParentMessageAndPhoto(params.getAdminId().toString(), params.getStoreId(),
                OrderParentMessageType.ORDER_STATUS_PLACE.getCode(), params.getOrderParentNo(), orderParent.getStatus(), messageContent, params.getPhoto());
        return true;
    }

    @Transactional
    @Override
    public boolean editInspection(StoreInspectionParams params) {
        Date now = new Date();
        Order order = orderService.findByOrderNo(params.getOrderNo());
        Order updateOrder = new Order();
        updateOrder.setUpdateBy(params.getAdminId().toString());
        updateOrder.setUpdateTime(now);
        updateOrder.setInspectionPhoto(params.getPhoto());
        updateOrder.setInspectionRemark(params.getRemark());
        boolean b = orderService.updateByOrderNo(updateOrder, params.getOrderNo());

        orderMessageService.addOrderMessage(params.getOrderNo(), params.getAdminId().toString(), "修改质检单", order.getStatus(), order.getOrderParentNo(), params.getPhoto(), params.getRemark(), OrderMessageTypeEnum.EDIT_INSPECTION, params.getAdminId().toString());
        return b;
    }

    @Transactional
    @Override
    public boolean editInvoice(StoreInvoiceParams params) {
        Date now = new Date();
        OrderParent orderParent = orderParentServiceImpl.getOrderParent(params.getOrderParentNo());
        OrderParent updateOrderParent = new OrderParent();
        updateOrderParent.setUpdateBy(params.getAdminId().toString());
        updateOrderParent.setUpdateTime(now);
        updateOrderParent.setInvoicePhoto(params.getPhoto());
        updateOrderParent.setInvoiceRemark(params.getRemark());
        boolean b = orderParentServiceImpl.updateByOrderParentNo(params.getOrderParentNo(), updateOrderParent);

        orderParentMessageService.addOrderParentMessageAndPhotoAndRemark(
                params.getAdminId().toString()
                , params.getStoreId()
                , OrderParentMessageType.ORDER_INVOICE.getCode()
                , params.getOrderParentNo()
                , orderParent.getStatus()
                , "修改发货单"
                , params.getPhoto()
                , params.getRemark());

        return b;
    }

    @Override
    public String editRealDeliveryTime(StoreEditRealDeliveryTimeParams params) {
        OrderParent orderParent = new OrderParent();
        orderParent.setUpdateBy(params.getAdminId().toString());
        Date now = new Date();
        orderParent.setUpdateTime(now);
        orderParent.setRealDeliveryTime(params.getRealDeliveryTime());
        boolean b = orderParentServiceImpl.updateByOrderParentNo(params.getOrderParentNo(), orderParent);
        log.info("更新母单平台实际发货时间成功:{} {}", params.getOrderParentNo(), params.getRealDeliveryTime());

        LambdaQueryWrapper<Order> wrapper = new LambdaQueryWrapper<>();
        wrapper.eq(Order::getOrderParentNo, params.getOrderParentNo());
        Order order = new Order();
        order.setRealDeliveryTime(params.getRealDeliveryTime());
        order.setUpdateBy(params.getAdminId().toString());
        order.setUpdateTime(now);
        orderService.update(order,wrapper);
        log.info("更新母单下所有子单平台实际发货时间成功:{} {}", params.getOrderParentNo(), params.getRealDeliveryTime());

        OrderParent queryOrderParent = orderParentServiceImpl.getOrderParent(params.getOrderParentNo());
        String messageContent = "修改平台实际发货时间为:" + DateUtil.dateFormate(params.getRealDeliveryTime(), "yyyy-MM-dd");
        orderParentMessageService.addOrderParentMessage(params.getAdminId().toString(), params.getStoreId(), OrderParentMessageType.EDIT_EXPECTED_DELIVERY_TIME.getCode(), params.getOrderParentNo(), queryOrderParent.getStatus(), messageContent);
        return params.getOrderParentNo();
    }

    @Override
    public String editOrderPriceAndRemark(StoreEditOrderPriceParams params) {
        //根据订单json修改订单子项价格,备注和图片
        //json格式:[{"orderNo":123,"details":[{"productId":123,"skuId":123,"remark":"abc","followImg":"aaaa"},{"productId":123,"skuId":123,"remark":"abc","followImg":"aaaa"}]}]
        String orderParams = params.getOrderParams();
        String orderParentNo = params.getOrderParentNo();
        List<OrderParamsDTO> dtos = JSON.parseArray(orderParams, OrderParamsDTO.class);
        dtos.forEach(o ->{
            List<OrderDetailParamsDTO> details = o.getDetails();
            details.forEach(detail ->{
//                editOrderAndDetailPrice(detail,orderNo);
            });
        });
        return "";
    }

    @Transactional
    @Override
    public String editSpecifyDeliveryTime(StoreEditSpecifyDeliveryTimeParams params) {
        Date now = new Date();
        LambdaQueryWrapper<Order> wrapper = new LambdaQueryWrapper<>();
        wrapper.eq(Order::getOrderParentNo, params.getOrderParentNo());
        Order order = new Order();
        order.setSpecifyDeliveryTime(params.getSpecifyDeliveryTime());
        order.setUpdateBy(params.getAdminId().toString());
        order.setUpdateTime(now);
        orderService.update(order,wrapper);
        return params.getOrderParentNo();
    }

    private static @NotNull CellStyle createStyle(Workbook workbook) {
        CellStyle style = workbook.createCellStyle();
        // 设置边框
        style.setBorderTop(BorderStyle.THIN); // 顶部边框
        style.setBorderBottom(BorderStyle.THIN); // 底部边框
        style.setBorderLeft(BorderStyle.THIN); // 左边边框
        style.setBorderRight(BorderStyle.THIN); // 右边边框
        return style;
    }

    @Transactional
    public void updateEstimatedDeliveryTimeTransactional(String orderParentNo, Date estimatedDeliveryTime) {
        OrderParent orderParent = orderParentServiceImpl.getOrderParent(orderParentNo);
        if (!OrderParentStatusEnum.WAIT_SEND.getCode().equals(orderParent.getStatus())) {
            return;
        }
        if (Objects.isNull(orderParent.getEstimatedDeliveryTime()) || estimatedDeliveryTime.after(orderParent.getEstimatedDeliveryTime())) {
            //如果没有设置过预计发货时间，或者新设置的时间大于之前的时间，则更新
            OrderParent updateOrderParent = new OrderParent();
            updateOrderParent.setEstimatedDeliveryTime(estimatedDeliveryTime);
            updateOrderParent.setUpdateTime(new Date());
            updateOrderParent.setUpdateBy("系统");
            orderParentServiceImpl.updateByOrderParentNo(orderParentNo, updateOrderParent);
        }

        List<Order> orderList = orderService.findByOrderParentNo(orderParentNo);
        List<Order> noCheckList = orderList.stream().filter(order -> OrderStatusEnum.WAIT_CHECK.getCode().equals(order.getStatus())).collect(Collectors.toList());
        //如果没有设置过预计发货时间，或者新设置的时间大于之前的时间，则更新
        if (CollectionUtils.isEmpty(noCheckList)) {
            //如果全部都已经确认过了就更新指定工厂发货时间
            Order order = new Order();
            order.setSpecifyDeliveryTime(estimatedDeliveryTime);
            order.setUpdateTime(new Date());
            order.setUpdateBy("系统");
            LambdaQueryWrapper<Order> wrapper = new LambdaQueryWrapper<>();
            wrapper.eq(Order::getOrderParentNo, orderParentNo);
            orderService.update(order, wrapper);
        }

    }


    @Override
    public ConfirmOrderParentDTO againConfirmOrder(AgainConfirmOrderParams confirmOrderParams, User user) {
        try {
            if (StringUtils.isBlank(confirmOrderParams.getOrderParentNo())) {
                throw new LaiKeAPIException(ErrorCode.BizErrorCode.ERROR_CODE_HQDDQRXXSB, "未查询母单信息", "againConfirmOrder");
            }
            List<OrderDetail> details = orderDetailService.findByOrderParentNo(confirmOrderParams.getOrderParentNo());
            if (CollectionUtils.isEmpty(details)) {
                throw new LaiKeAPIException(ErrorCode.BizErrorCode.ERROR_CODE_HQDDQRXXSB, "未查询母单信息", "againConfirmOrder");
            }
            //获取未下架的商品和未下架的sku列表
            List<ProductListModel> productListModelsByCarts = getProductListModelsByOrderDetailIds(details);
            if (CollectionUtils.isEmpty(productListModelsByCarts)) {
                throw new LaiKeAPIException(ErrorCode.BizErrorCode.ERROR_CODE_HQDDQRXXSB, "未查询到商品信息", "confirmOrder");
            }
            List<OrderDetail> orderDetails = new LinkedList<>(details);
            List<Integer> offlineProductIds = new ArrayList<>(productListModelsByCarts.size());
            for (ProductListModel productListModel : productListModelsByCarts) {
                if ("3".equals(productListModel.getStatus())) {
                    offlineProductIds.add(productListModel.getId());
                }
            }
            Iterator<OrderDetail> iterator = orderDetails.iterator();
            if (!CollectionUtils.isEmpty(offlineProductIds)) {
                while (iterator.hasNext()) {
                    OrderDetail orderDetail = iterator.next();
                    if (offlineProductIds.contains(orderDetail.getProductId())) {
                        iterator.remove();
                    }
                }
            }

            if (CollectionUtils.isEmpty(orderDetails)) {
                throw new LaiKeAPIException(ErrorCode.BizErrorCode.ERROR_CODE_HQDDQRXXSB, "所有商品都已下架", "againConfirmOrder");
            }

            List<ConfiGureModel> skuList = getSkuListByOrderDetails(orderDetails);
            if (CollectionUtils.isEmpty(skuList)) {
                throw new LaiKeAPIException(ErrorCode.BizErrorCode.ERROR_CODE_HQDDQRXXSB, "未查询到商品sku信息", "againConfirmOrder");
            }

            //删除已下架的sku
            List<Integer> offLineSkuIds = new ArrayList<>(skuList.size());
            for (ConfiGureModel confiGureModel : skuList) {
                if ("3".equals(confiGureModel.getStatus())) {
                    offLineSkuIds.add(confiGureModel.getId());
                }
            }
            iterator = orderDetails.iterator();
            if (!CollectionUtils.isEmpty(offLineSkuIds)) {
                while (iterator.hasNext()) {
                    OrderDetail orderDetail = iterator.next();
                    if (offLineSkuIds.contains(orderDetail.getSkuId())) {
                        iterator.remove();
                    }
                }
            }
            if (CollectionUtils.isEmpty(orderDetails)) {
                throw new LaiKeAPIException(ErrorCode.BizErrorCode.ERROR_CODE_HQDDQRXXSB, "未查询到商品信息", "confirmOrder");
            }

            //获取商品列表
            List<ProductListModel> productModelLists = getProductListModelsByOrderDetailIds(orderDetails);
            user = getUser(user.getStore_id(), user.getUser_id());
            //生成母单/子单/订单子项数据
            UserPlaceOrderParams params = new UserPlaceOrderParams();
            params.setUser(user);
            params.setOrderType(OrderTypeEnum.SELF.getCode());
            params.setOperationType(OrderOperationTypeEnum.USER.getCode());
            String discount = publicMemberService.getMemberDiscountByToken(confirmOrderParams.getAccessId(), confirmOrderParams.getStoreId());
            params.setRate(new BigDecimal(discount));
            params.setStoreId(confirmOrderParams.getStoreId());
            params.setInvoice(OrderInvoiceEnum.YES.getCode());
            //将orderDetails转换为cartModels,因为都调用的统一的getOrderCombiner 传递的是 List<CartModel>,但是没有ID,是不允许查询购物车
            List<CartModel> cartModels = getCartModelsByOrderDetails(orderDetails);
            params.setCartModels(cartModels);
            OrderCombiner orderCombiner = orderParentServiceImpl.getOrderCombiner(params, productModelLists);
            if (CollectionUtils.isEmpty(orderCombiner.getOrders())
                    || CollectionUtils.isEmpty(orderCombiner.getDetails())
                    || Objects.isNull(orderCombiner.getOrderParent())
            ) {
                throw new RuntimeException("获取确认订单失败");
            }
            Map<Integer, MchModel> mchModelMap = orderParentServiceImpl.getMchModelMap(productModelLists);
            OrderParent orderParent = orderCombiner.getOrderParent();
            ConfirmOrderParentDTO confirmOrderParentDTO = new ConfirmOrderParentDTO();
            confirmOrderParentDTO.setOrders(orderParentServiceImpl.getConfirmOrders(orderCombiner.getOrders(), orderCombiner.getDetails(), mchModelMap));
            confirmOrderParentDTO.setTaxation(PriceUtil.longToBigDecimalPrice(orderParent.getTaxation()));
            confirmOrderParentDTO.setTotalPrice(PriceUtil.longToBigDecimalPrice(orderParent.getTotalPrice()));
            confirmOrderParentDTO.setTotalVolume(orderParent.getTotalVolume());

            List<String> orderDetailIds = details.stream().map(s -> String.valueOf(s.getId())).collect(Collectors.toList());
            confirmOrderParentDTO.setOrderDetailIds(String.join(SPLIT_STR, orderDetailIds));
            return confirmOrderParentDTO;
        } catch (LaiKeAPIException e) {
            log.error("获取确认订单失败 异常", e);
            throw e;
        } catch (Exception e) {
            log.error("获取确认订单失败 异常", e);
            throw new LaiKeAPIException(ErrorCode.BizErrorCode.ERROR_CODE_HQDDQRXXSB, "获取确认订单失败", "confirmOrder");
        }
    }


    @Override
    public String againPlaceOrder(AgainPlaceOrderParams vo, User user) {
        try {
            String orderDetailIdsStr = vo.getOrderDetailIds();
            if (StringUtils.isBlank(orderDetailIdsStr)) {
                throw new LaiKeAPIException(ErrorCode.BizErrorCode.ORDER_FAILED_TRY_AGAIN_LATER, "下单失败", "againPlaceOrder");
            }
            String[] orderDetailsIds = orderDetailIdsStr.split(SPLIT_STR);
            List<OrderDetail> orderDetails = orderDetailService.findByIds(Arrays.asList(orderDetailsIds));

            UserAddress userAddress = new UserAddress();
            userAddress.setName(vo.getName());
            userAddress.setTel(vo.getTel());
            userAddress.setAddress(vo.getAddress());
            userAddress.setSheng(vo.getSheng());
            userAddress.setCity(vo.getCity());
            userAddress.setQuyu(vo.getQuyu());
            UserPlaceOrderParams params = PlaceOrderParamsMapstructMapper.INSTANCE.againToDTO(vo);
            String discount = publicMemberService.getMemberDiscountByToken(vo.getAccessId(), vo.getStoreId());

            List<CartModel> cartModels = getCartModelsByOrderDetails(orderDetails);
            if (CollectionUtils.isEmpty(cartModels)) {
                throw new LaiKeAPIException(ErrorCode.BizErrorCode.ORDER_FAILED_TRY_AGAIN_LATER, "下单失败", "againPlaceOrder");
            }
            int payType;
            if (OrderInvoiceEnum.YES.getCode().equals(vo.getInvoice())) {
                //开票 走线下自营订单
                payType = OrderTypeEnum.SELF.getCode();
                params.setOrderType(OrderTypeEnum.SELF.getCode());
            } else {
                //不开票走结算通
                payType = OrderTypeEnum.POP.getCode();
                params.setOrderType(OrderTypeEnum.POP.getCode());
            }
            user = getUser(user.getStore_id(), user.getUser_id());
            params.setUser(user);
            params.setRate(new BigDecimal(discount));
            params.setExpectedDeliveryTime(vo.getExpectedDeliveryTime());
            params.setInvoice(vo.getInvoice());
            params.setCartModels(cartModels);
            params.setUserAddress(userAddress);
            params.setStoreId(vo.getStoreId());
            params.setPayType(payType);
            params.setRemark(vo.getRemark());
            params.setRemarks(vo.getRemarks());
            OrderParentDTO orderParentDTO = orderParentServiceImpl.submitOrder(params, false);
            //假如订单超时处理的延时队列
            OrderCancelRunner.addOrderCancel(orderParentDTO.getOrderParentNo());
            return orderParentDTO.getOrderParentNo();
        } catch (LaiKeAPIException e) {
            log.error("下单失败 异常", e);
            throw e;
        } catch (Exception e) {
            log.error("下单失败 异常", e);
            throw new LaiKeAPIException(ErrorCode.BizErrorCode.ORDER_FAILED_TRY_AGAIN_LATER, "下单失败", "placeOrder");
        }
    }

    private List<ProductListModel> getProductListModelsByOrderDetailIds(List<OrderDetail> orderDetails) {
        List<Integer> productIdList = orderDetails.stream().map(OrderDetail::getProductId).collect(Collectors.toList());

        Example example = new Example(ProductListModel.class);
        Example.Criteria criteria = example.createCriteria();
        criteria.andIn("id", productIdList);
        return productListModelMapper.selectByExample(example);
    }


    private List<ConfiGureModel> getSkuListByOrderDetails(List<OrderDetail> orderDetails) {
        List<String> skuIds = orderDetails.stream().map(OrderDetail::getSkuId).collect(Collectors.toList());

        Example example = new Example(ConfiGureModel.class);
        Example.Criteria criteria = example.createCriteria();
        criteria.andIn("id", skuIds);
        return configureModelMapper.selectByExample(example);
    }

    private User getUser(Integer storeId, String userId) {
        User user = new User();
        user.setUser_id(userId);
        user.setStore_id(storeId);
        return userMapper.selectOne(user);
    }


    public List<CartModel> getCartModelsByOrderDetails(List<OrderDetail> orderDetails) {
        List<CartModel> cartModels = new ArrayList<>();
        if (!CollectionUtils.isEmpty(orderDetails)) {
            for (OrderDetail orderDetail : orderDetails) {
                CartModel cartModel = new CartModel();
                cartModel.setGoods_id(orderDetail.getProductId());
                cartModel.setGoods_num(orderDetail.getNum());
                cartModel.setSize_id(orderDetail.getSkuId());
                cartModel.setStore_id(orderDetail.getStoreId());
                cartModel.setUser_id(orderDetail.getUserId());
                cartModels.add(cartModel);
            }
        }
        return cartModels;
    }

    public void editOrderAndDetailPrice(OrderDetailParamsDTO dto,String orderParentNo){
        Long supplierPrice = dto.getSupplierPrice();
        if(Objects.isNull(dto.getSkuId()) || StringUtils.isBlank(orderParentNo)){
            throw new LaiKeAPIException("参数错误");
        }
        if(Objects.nonNull(supplierPrice)){
            List<OrderDetail> orderDetails = orderDetailService.findByOrderParentNo(orderParentNo);

        }

    }



}
